<template>
  <!-- App.vue -->
  <div style="width: 100%; height: 100%">
<!--    <n-space vertical :size="12">-->
      <n-input style="height: 5%"  v-model:value="pattern" round size="small" placeholder="搜索">
        <template #suffix>
          <n-icon>
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
              <g fill="none">
                <path
                    d="M12 10c4.418 0 8-1.79 8-4s-3.582-4-8-4s-8 1.79-8 4s3.582 4 8 4zm6.328.17A7.61 7.61 0 0 0 20 9.053v3.204a5.477 5.477 0 0 0-4.02-1.233a11.687 11.687 0 0 0 2.348-.854zM11 16.5a5.502 5.502 0 0 0 3.831 5.242c-.88.167-1.834.258-2.831.258c-4.418 0-8-1.79-8-4V9.053a7.61 7.61 0 0 0 1.672 1.117C7.37 11.018 9.608 11.5 12 11.5c.958 0 1.892-.077 2.777-.225A5.502 5.502 0 0 0 11 16.5zm5.5 4.5a4.48 4.48 0 0 0 2.607-.832l2.613 2.612a.75.75 0 1 0 1.06-1.06l-2.612-2.613A4.5 4.5 0 1 0 16.5 21zm0-1.5a3 3 0 1 1 0-6a3 3 0 0 1 0 6z"
                    fill="currentColor"></path>
              </g>
            </svg>
          </n-icon>
        </template>
      </n-input>
      <n-tree
          :show-irrelevant-nodes="showIrrelevantNodes"
          :pattern="pattern"
          :data="tree"
          block-line
          :on-load="handleLoad"
          :virtual-scroll="true"
          :style="{height: windowHeight * 0.95 * 0.90 + 'px'}"
          :node-props="nodeProps"
          :expanded-keys="expandedKeys"
          @update:expanded-keys="handleExpandedKeysChange"

      />
      <n-dropdown
          trigger="manual"
          placement="bottom-start"
          :show="showDropdownRef"
          :options="menuOptions"
          :x="xRef"
          :y="yRef"
          @select="handleSelect"
          @clickoutside="handleClickoutside"
      />
<!--    </n-space>-->
  </div>

</template>

<script lang="ts" setup>
import {ref, PropType, defineEmits, onMounted,nextTick} from 'vue'
import {DropdownOption, TreeOption} from 'naive-ui'
import {
  SchemasOperation,
} from "../../../model/mysql/TreeOperationInfo";
import {ipcRenderer} from 'electron';
import MySqlConnectInfo from "../../../model/mysql/MySqlConnectInfo";
import ResultDTO from "../../../model/ResultDTO";
import {closeConnect, openConnectAndReturnDatabases, testConnect, listenToMainEvent} from "../../../renderer/tree/DataSourceTreeUtils";
import {
  ViewObjectOperationEnum, ViewObjectData
} from '../object/ViewObjectData'
import {sqliteDeleteConnectInfo, sqliteGetConnectInfoList} from '../../../renderer/SqliteRenderer'
import ConnectSourceOperationEnum from "../../../enum/tree/ConnectSourceOperationEnum";
import DataBaseOperationEnum from "../../../enum/tree/DataBaseOperationEnum";

//处理展开节点
const expandedKeys = ref<string[]>([]);
//消息通知
//右键菜单
const menuOptions = ref()
//点击数据库时、点击表时
const emit = defineEmits(['clickDatabase', 'clickTable', 'clickMenu'])

const showDropdownRef = ref(false)
//右键时当前选中节点
const optionsRef = ref<DropdownOption>()
const xRef = ref(0)
const yRef = ref(0)
//map
const MysqlConnectInfoMap = ref<Map<number, MySqlConnectInfo>>(new Map());
const pattern = ref('');
const showIrrelevantNodes = ref(false)
const tree = ref<TreeOption[]>([])
const message = useMessage();
const nodeProps = ({option}: { option: TreeOption }) => {
  return {
    onClick() {
      // message.info('[Click] ' + option.label)
      //测试数据库是否正常
      let key: string = <string>option.key
      let keyArr = key.split("#")
      let level: number = parseInt(keyArr[0])
      // if (level === 1){
      //   emit('clickDatabase', {
      //     connectName,
      //     type: ViewObjectOperationEnum.CONNECT_INFO
      //   })
      // }
      console.log("click", option)
      let connectId = parseInt(keyArr[1]);

      //数据库层
      if (level === 2) {
        let database = keyArr[2];
        let viewObjectData: ViewObjectData = {
          id: connectId,
          connectName: <string>option.label,
          dataBase: database,
          type: ViewObjectOperationEnum.DATABASE,
          //表是在第一个
          tableSize: option.children?.[0].children ? option.children[0].children?.length : 0
        }
        emit('clickDatabase', viewObjectData)
      }
      else if (level === 3){

      }
      //点击表时
      else if (level === 4) {
        let connectName = keyArr[1];
        let database = keyArr[2];
        let operation = keyArr[3];
        let tableName = keyArr[4];

        let viewObjectData: ViewObjectData = {
          id: connectId,
          connectName: <string> option.label, dataBase: database,
          tableName: tableName,
          type: ViewObjectOperationEnum.TABLE
        }
        emit('clickTable', viewObjectData)
      }
    },
    onContextmenu(e: MouseEvent): void {
      optionsRef.value = option
      let key: string = <string>option.key
      let keyArr = key.split("#")
      let level: number = parseInt(keyArr[0])
      if (level === 1) {
        if (option.children){
          menuOptions.value  =  ConnectSourceOperationEnum.getCloseConnectOperation();

        }else{
          menuOptions.value =  ConnectSourceOperationEnum.getOpenConnectOperation();
        }
      } else if (level === 2) {
        menuOptions.value = DataBaseOperationEnum.getDatabaseOperation(option)
      } else if (level === 3) {
        menuOptions.value = [
          {
            label: '打开',
            key: 'table_open',
            show: true
          },
          {
            label: '新建表',
            key: 'table_new',
            show: true
          },
          {
            label: '刷新',
            key: 'table_refresh',
            show: true
          }
        ]
      }else if (level === 4){
        menuOptions.value = [
          {
            label: '打开表',
            key: 'table_open',
            show: true
          },
          {
            label: '删除表',
            key: 'table_delete',
            show: true
          },
          {
            label: '设计表',
            key: 'table_edit',
            show: true
          }
        ]

      }
      console.log("option:", option)
      showDropdownRef.value = true
      xRef.value = e.clientX
      yRef.value = e.clientY
      console.log(e.clientX, e.clientY)
      e.preventDefault()
    }
  }
}




// 处理节点展开的事件
const handleExpandedKeysChange = (expandedKeysParams: string[]) => {
  console.log("handleExpandedKeysChange ", expandedKeysParams)
  if (expandedKeysParams) {
    expandedKeys.value = expandedKeysParams
  }
}
// 处理节点收起的事件
const handleCollapse = (key, node) => {
  const index = expandedKeys.value.indexOf(key);
  console.log("handleCollapse node", node, index, expandedKeys)

  if (index > -1) {
    expandedKeys.value.splice(index, 1);
  }
};
// 通过代码展开节点
const expandNodeByKey = (nodeKey: string) => {
  // 如果节点key不在expandedKeys中，则添加到数组中
  if (!expandedKeys.value.includes(nodeKey)) {
    expandedKeys.value.push(nodeKey);
  }
}
const handleSelect = (e) => {
  showDropdownRef.value = false
  let node: TreeOption = optionsRef.value;
  let key: string = <string>node.key
  let keyArr = key.split("#")
  let level: number = parseInt(keyArr[0])
  let connectId = parseInt(keyArr[1])

  let closeFunction = () => {
    if (node.children){
      node.loading = true;
      console.log(ConnectSourceOperationEnum.closeConnection, optionsRef.value)
      closeConnect(connectId, node).then((res)=>{
        message.success("关闭成功")
        node.children = undefined;
      }).catch(res=>{
        message.error("关闭错误, " + res.message)
      })
      node.loading = false;
      handleCollapse(node.key, node)
    }
  }
  //把所有操作都回显到父组件
  //第一层的菜单
  if (level === 1){
    if (ConnectSourceOperationEnum.closeConnection.code == e) {
      closeFunction();
      node.children = undefined;
    } else if (ConnectSourceOperationEnum.openConnect.code == e) {
      node.loading = true;
      handleLoad(node);
      node.loading = false;

    }else if (ConnectSourceOperationEnum.editConnection.code == e) {
      //编辑时需要关闭链接
      closeFunction();
    }else if (ConnectSourceOperationEnum.deleteConnect.code === e){
      closeFunction();
      for (let i = 0; i < tree.value.length; i++) {
        //移除当前节点
        if (tree.value[i].key === node.key){
          tree.value.splice(i);
        }
      }
      sqliteDeleteConnectInfo(MysqlConnectInfoMap.value.get(connectId))
          .then(res=>{
            message.success("删除成功");
          })
          .catch(rs=>{

          })

    }
  }
  emit('clickMenu',tree, e , level, keyArr, node, MysqlConnectInfoMap.value);
  console.log("menu click test", e)

}
const handleClickoutside = (e) => {
  showDropdownRef.value = false
  console.log("menu click", e)
}


//加载sqllite里面的配置信息
//先加载跟节点
//增加主节点
nextTick(()=>{
  sqliteGetConnectInfoList().then((res: ResultDTO<MySqlConnectInfo[]>)=>{
    console.log("res", res)

    if (res.result){
      for (let mySqlConnectInfo: MySqlConnectInfo of res.result) {
        let treeOption: TreeOption = {
          label: mySqlConnectInfo.connectName,
          key: '1#' + mySqlConnectInfo.id,
          isLeaf: false,
        }
        tree.value.push(treeOption);
        if (mySqlConnectInfo.id != null) {
          MysqlConnectInfoMap.value.set(mySqlConnectInfo.id, mySqlConnectInfo);
        }
      }
    }
    console.log("MysqlConnectInfoMap", MysqlConnectInfoMap)
  }).catch(resJson=> {
    console.log("test", resJson)
    let res: ResultDTO<MySqlConnectInfo[]> = JSON.parse(resJson);
    message.error('链接列表加载失败,' + res.message)
  })
})

const handleLoad = (node: TreeOption) => {
  //测试数据库是否正常
  let key: string = <string>node.key
  let keyArr = key.split("#")
  let level: number = parseInt(keyArr[0])
  //这个是数据库的ID
  let connectId = parseInt(keyArr[1])
  let connectName = <string> node.label;
  console.log("handleLoad：", node)
  if (level === 1) {
    let connectInfo: MySqlConnectInfo = MysqlConnectInfoMap.value.get(connectId);
    return new Promise<void>((resolve) => {
      testConnect(connectInfo).then((rs: ResultDTO<any>) => {
        openConnectAndReturnDatabases(connectInfo).then((res: ResultDTO<any>) => {
              //成功加载
              let secondTree: TreeOption[] = []
              //加载数据库信息
              if (res.result) {
                for (let datum: any of res.result) {
                  let databaseTree: TreeOption = {
                    key: '2#' + connectId + '#' + datum.Database,
                    label: datum.Database,
                    isLeaf: false,
                  }
                  secondTree.push(databaseTree)
                }
                node.children = secondTree
                setTimeout(() => {
                  expandNodeByKey(<string>node.key);

                }, 1000)
              } else {
                node.children = []
              }
              node.loading = false;
              resolve()
            }
        ).catch((error) => {
          console.log("err", error)
          node.loading = false;
          message.error( "链接数据库失败," + JSON.stringify(error))
          resolve(false)
        })
      }).catch((res: ResultDTO<any>) => {
        console.log("链接错误 err", res)
        message.error("链接错误," + res.message)
        node.loading = false;
        resolve(false)
      })
    })
  }else if (level === 2){
    let database = keyArr[2];
    node.children =  [
      {
        label: SchemasOperation.Table,
        key: '3#' + connectId + '#' + database + '#' + SchemasOperation.Table,
        isLeaf: false
      },
      {
        label: SchemasOperation.View,
        key: '3#' + connectId + '#' + database + '#' + SchemasOperation.View,
        isLeaf: false
      },
      {
        label: SchemasOperation.Function,
        key: '3#' + connectId + '#' + database + '#' + SchemasOperation.Function,
        isLeaf: false
      },
      {
        label: SchemasOperation.Query,
        key: '3#' + connectId + '#' + database + '#' + SchemasOperation.Query,
        isLeaf: false
      },
      {
        label: SchemasOperation.Event,
        key: '3#' + connectId + '#' + database + '#' + SchemasOperation.Event,
        isLeaf: false
      }
    ]

    return new Promise<void>((resolve)=>{
      handleLoad(node.children?.[0]).then(res=>{
        //加载完当前的表，重新发送时间
        let viewObjectData: ViewObjectData = {
          id: connectId,
          connectName: connectName, dataBase: database,
          type: ViewObjectOperationEnum.DATABASE,
          tableSize: node.children?.[0].children?.length
        }
        emit('clickDatabase', viewObjectData)
        resolve();
      })
    })
    //加载表
  }
  else if (level === 3) {
    return new Promise<void>((resolve) => {
      //层级 # connect # database # 视图

      let connectId= parseInt(keyArr[1]);
      let database = keyArr[2];
      let operation = keyArr[3];
      let connectInfo: MySqlConnectInfo = MysqlConnectInfoMap.value.get(connectId)
      if (SchemasOperation.Table === operation) {
        ipcRenderer.invoke('get-database-table-list', connectInfo.id, database)
            .then(res => {
              console.log("tables " + database, " :", res)
              if (res) {
                let list: TreeOption[] = []
                for (let datum of res) {
                  let tableName = datum['Tables_in_' + database.toLowerCase()]
                  // console.log("table",tableName)
                  let tableOption: TreeOption = {
                    label: tableName,
                    key: '4#' + connectId + '#' + database + '#' + operation + '#' + tableName,
                    isLeaf: true
                  }
                  list.push(tableOption);
                }
                node.children = list
              } else {
                node.children = []
              }

              resolve()
            }).catch(err => {
          console.log("err", err)
        })

      }
    })
  }

}


const windowWidth = ref(0);
const windowHeight = ref(0);
//获取拖动的窗口
ipcRenderer.on('window-resize', (event, {width, height}) => {
  // 可以根据需求将宽度和高度传递到组件的数据属性中
  windowWidth.value = width;
  windowHeight.value = height;
});

listenToMainEvent(tree.value, MysqlConnectInfoMap.value);

</script>